Wonder Site (new-site based)
Overview
Use this skill inside wonder-image/new-site or any project scaffolded from it. The repo is the runtime owner. The framework lives in vendor/wonder-image/app (Composer, see wi-app for changes there) and the JS/CSS design system lives under assets/lib/wonder-image/dist/ (copied from npm wonder-image/lib). Treat both as upstream — never edit them in place.
Glossary
Shared vocabulary across wi-app and wi-site (identical wording in both skills):
- framework —
wonder-image/app (Composer package, github.com/wonder-image/app). Lives at the repo root when wi-app is active; lives at vendor/wonder-image/app/ inside a site.
- lib —
wonder-image/lib (npm package, github.com/wonder-image/lib). The JS / CSS design system. Source at node_modules/wonder-image/src/; compiled copy at assets/lib/wonder-image/dist/.
- scaffold —
wonder-image/new-site (github.com/wonder-image/new-site). The site template. The scaffold itself is also a valid site.
- site — any project whose
composer.json depends on wonder-image/app (i.e. installs the framework under vendor/wonder-image/app). Typically the scaffold or a project derived from it. Canonical term — prefer "site" over older mixed uses like "consumer project" / "consumer app".
- module — external Composer package
wonder-image/<slug> discovered via Composer (or filesystem fallback). Ships its own models / resources / routes via module.json + a ModuleInterface entrypoint.
custom/ — site-only directory for project pages, components, layouts, routes, config, and helpers. Never present inside the framework.
app/Models / app/Resources — site PSR-4 roots (App\Models\... / App\Resources\...). Distinct from the framework's class/App/Models / class/App/Resources (Wonder\App\Models\... / Wonder\App\Resources\...).
When to switch to wi-app
Stop and switch to wi-app when any of these signals are true — the work belongs in the framework, not in this site (the frontmatter SKIP block already encodes the router-side check; this is the working-time version):
- the repo's
composer.json declares "name": "wonder-image/app" (you are inside the framework repo, not a site).
- the requested change lives under
vendor/wonder-image/app/. Never patch vendor from a site. Either reshape the change to live in custom/ / app/Models / app/Resources (stays wi-site), or open the change against the framework repo (then wi-app applies).
- you need to add or modify a
Model / Resource base class, a FormField helper, an element under class/Elements/, a theme renderer under class/Themes/{Wonder,Bootstrap}/, a route in app/config/routes/*, the module discovery flow, the bootstrap order, the permission builder registry at app/config/app/permission.php, or a shared user-management resource.
- the task is "add a new form input type", "change how the framework renders inputs in Wonder vs Bootstrap", "extend the permission builder", "register a new console command source", or any work that defines (rather than uses) framework behavior.
- working in
wonder-image/lib (the JS / CSS design-system source) — that is a different repo entirely; neither wi-site nor wi-app applies.
Non-Negotiable Rules
- Never edit
vendor/, node_modules/, or assets/lib/wonder-image/dist/. The last one is regenerated by npm install from wonder-image/lib.
- Never patch
vendor/wonder-image/app from a site task. If the change belongs there, switch to wi-app.
- Never run these Forge commands from this skill:
php forge config
php forge credentials
php forge provision
php forge db:init
php forge build
- Every user-facing string goes through
__t(...) with entries in lang/{locale}/*.json (any number of JSON files: pages.json, components.json, emails.json, legal.json, plus any new ones the site needs). URLs go through __r(string $name, array $parameters = []) (preferred — builds the URL from a named route, picks up the active locale, survives route renames). Use __u(string $path) only when there is no named route and you must build a URL from a free path (e.g. __u('contact')). No hardcoded copy or language prefixes in PHP.
- Before writing new CSS classes, JS behavior, or UI structure, inspect
wonder-image/lib and reuse the existing design system. Full UI rulebook in references/style-and-lib.md — read it for any UI / styling / design-system task. The default mode is USE the lib, do not MODIFY it.
- Never hardcode colors (HEX / RGB / HSL), introduce
.wi-* (or any other) prefix-based naming, or build a parallel CSS system. Detect {ASSETS_VERSION} dynamically — do not assume 0.0/ or any other version.
- Prefer external Composer modules
wonder-image/<slug> over project-embedded module code.
- Place PSR-4 classes under
app/Models and app/Resources with namespace App\Models / App\Resources. Place project pages, components, layout overrides, routes, config, and helpers under custom/.
- The canonical model / table flow is
Model::tableSchema() + Model::dataSchema(). Do not invent parallel table definition systems alongside it.
Start Sequence
Read PRODUCT.md at the site root first. It defines register (brand vs product), site_type, target users, brand personality, voice/tone, design principles. Everything you do next must be coherent with what it says — placement choices, copy, suggestions of modules, UI direction.
If PRODUCT.md is missing or its required sections are empty, do NOT proceed with the user's task yet. Run the interview procedure in references/product-md.md § Compilation procedure: ask 2–4 focused questions at a time with AskUserQuestion, save answers into PRODUCT.md as they come, and continue interviewing until you have at least 80% project clarity — operationalized as: all 6 required sections filled (Register, Site type, Target users, Brand personality, Voice / tone, Design principles) plus at least one of (Anti-references, Asset paths). Only then proceed with the original task. Reason: the alternative is generic output that the user will have to fix later — the 10–15 minutes spent interviewing pay back on every subsequent decision in the session and in future sessions.
The interview is sequential and adaptive: if the user already mentioned something in passing (e.g. "abbiamo un brand di moda"), pre-fill the relevant section and ask for confirmation rather than re-asking from scratch. Full schema in references/product-md.md; copy-paste template in references/examples.md §6.
Classify the task:
- page or component work
- UI / styling / design-system work
- model, resource, repeater, or table work
- backend-editable content
- permissions, roles, or user areas
- translation, locale URLs, or content text
- module integration
- setup, runtime, or local environment
Read only the reference that matches the task (see Task Routing below). For copy-paste scaffolds (Model + Resource skeleton, frontend page, pages.json entry, permissions.php extension, modules.php), jump straight to references/examples.md.
Decide whether the work belongs in custom/, app/, an external wonder-image/<slug> module, or actually in the framework (switch to wi-app).
Refuse the wrong placement: no direct vendor/ patching, no hand-edited node_modules/ or assets/lib/wonder-image/dist/, no parallel user-management pages, no custom CSS inside assets/{ASSETS_VERSION}/css/set-up/.
Task Routing
Brand, copywriting, voice, site type
Read references/product-md.md. PRODUCT.md at site root is the source of truth for register, target users, brand personality, voice/tone, design principles, and site_type (landing / corporate / blog / ecom / rsvp). Copy lives in lang/{locale}/*.json and must respect the voice declared in PRODUCT.md. For deep UI critique / polish / audit beyond Wonder's reuse-first placement rules, hand off to the companion skill impeccable (npx skills add pbakaus/impeccable — it reads the same PRODUCT.md natively). Do not create a DESIGN.md — Wonder's color.css + root.css + style-and-lib.md are authoritative for visual tokens.
Page or component
Read references/implementation-playbook.md and references/style-and-lib.md. Copy-paste skeleton for a frontend page in references/examples.md.
- For a reusable header driven by one recursive navigation tree, read
references/header-navigation.md. It defines the classic / mega contract, list default, optional card presentation, action links, appearance options, desktop hover behavior, and the mobile cascade.
- Pages go under
custom/view/pages/{frontend,backend}/....
- Component overrides mirror the framework path under
custom/view/components/{frontend,backend}/....
- Reuse
\Wonder\View\View::component(...) over manual include.
- Inspect existing page components before adding new markup.
UI / styling / design system
Read references/style-and-lib.md first. Applies to every task touching buttons, inputs, forms, modals, cards, alerts, badges, typography, images, interactive elements, color tokens, root variables, or custom CSS / JS.
- Default mode: USE the lib, do not MODIFY it. Modifying
wonder-image/lib requires an explicit user request.
- Reuse existing lib classes and tokens before writing anything new. No
.wi-* (or other) prefix-based naming. No parallel CSS system. No hardcoded colors.
- Token files:
assets/{ASSETS_VERSION}/css/set-up/color.css and root.css. Custom CSS / JS goes under assets/{ASSETS_VERSION}/css/ and assets/{ASSETS_VERSION}/js/ — never inside set-up/.
- Detect
{ASSETS_VERSION} from the actual assets/ directory before reading or writing token files.
- End every UI task with the Required Final Report and Pre-Submit Checklist in
references/style-and-lib.md.
Model, resource, repeater, or table — site postilla
Read references/implementation-playbook.md for the placement workflow, then start from the skeleton in references/examples.md. For the full API contract (method signatures, lifecycle, registry behavior, repeater details), read wi-app/references/model-and-resource.md — install wi-app alongside wi-site to have it available locally.
Steps for a new site Model + Resource:
- Create the Model under
app/Models/<Name>.php, namespace App\Models, extending the framework Model base.
- Define SQL in
Model::tableSchema(). Define data behavior in Model::dataSchema().
- Create the Resource under
app/Resources/<Name>Resource.php, namespace App\Resources, bound to the Model.
- Define
formSchema() for backend inputs, permissionSchema() for route gating, navigationSchema() for nav placement.
- Use
FormField::repeater(...) + RepeaterColumn for repeatable rows; CustomPageSchema only for non-CRUD pages.
- Run
composer dump-autoload, then php forge update --local to apply runtime generation.
The canonical flow is Model::tableSchema() + Model::dataSchema(). Do not invent parallel table-definition files alongside it.
Backend-editable content
Read references/implementation-playbook.md. Prefer a real Model + Resource flow. Connect media to existing media resources. Never store editable content in static arrays or loose files.
Permissions, roles, or user areas — site postilla
The full builder API, framework user resources, and runtime $PERMITS export live in wi-app at wi-app/references/permissions-and-users.md. In a site, the only place to touch is:
custom/config/permissions.php — extends or overrides the registry after the base file (app/config/app/permission.php in the framework) and the module merge have run. Copy-paste skeleton in references/examples.md.
Steps to add or override a site permission:
- Open
custom/config/permissions.php.
- Extend the builder registry already initialized in
app/config/app/permission.php and then merged with module permissions.
- Reference the resulting permission key from any project
Resource::permissionSchema() and from navigation authority gates.
- Do not build parallel user-management pages — user CRUD is centralized in the shared framework resources. If a site truly needs a different user flow, that is a framework-level change → switch to wi-app.
If wi-app is not yet installed locally, run npx skills add wonder-image/skills --skill wi-app to make the full reference available.
Translation, locale URLs, content text
Read references/workflows.md. Sample lang/it/pages.json entry in references/examples.md.
- Strings live in
lang/{locale}/*.json — any number of JSON files. The site ships pages.json, components.json, emails.json, legal.json by default; new ones (e.g. lang/{locale}/terms.json) are picked up automatically.
- Access translated strings via
__t("path.to.key").
- Build URLs:
- Prefer
__r(string $name, array $parameters = []) — URL from a named route. Works for every route registered in app/config/routes/ or custom/routes/, including frontend pages, resource CRUD routes, and custom backend routes. Survives slug / path changes because it resolves by name.
- Fallback to
__u(string $path) only when no named route exists and you must build a locale-aware URL from a free path string (e.g. <a href="<?= __u('contact') ?>">).
Module integration
Read references/project-structure.md and references/workflows.md.
- Prefer external Composer packages
wonder-image/<slug> over embedded code.
- Enable modules in
custom/config/modules.php — copy-paste skeleton in references/examples.md.
Setup, runtime, or local environment
Read references/workflows.md. From the project root:
composer install (also runs php forge config via Composer scripts)
npm install (copies wonder-image/lib into assets/lib/wonder-image/dist/)
php forge credentials (only when the user explicitly requests Bitwarden dev-shared recovery; writes secrets into .env)
php forge update --local (applies DB and runtime generation)
php forge start (runs the local server, may fill missing .env)
Validation
- Run
php -l on every touched PHP file.
- Run
composer dump-autoload when PSR-4 classes are added, moved, or renamed.
- For integration-sensitive changes:
php forge update --local then php forge start.
- Re-run
npm install only when changes depend on assets/lib/wonder-image/dist/ from wonder-image/lib.
Output Expectations
- Name the concrete site paths changed (e.g.
custom/view/pages/frontend/about.php, app/Models/Project.php, lang/it/pages.json).
- State explicitly when a requested change actually belongs in the framework (→ wi-app) or in
wonder-image/lib.
- List translation file updates, permission/authority changes, and Forge/npm rebuild steps when relevant.
- Refuse, with a one-line reason, any edit to
vendor/, node_modules/, assets/lib/wonder-image/dist/, or any Forge-generated file.
1---2name: wi-site3description: Work inside wonder-image/new-site or any site scaffolded from it. Use when composer.json depends on `wonder-image/app` but is not the framework package, or when work touches `custom/`, `app/Models`, `app/Resources`, `lang/`, `assets/{ASSETS_VERSION}/`, `PRODUCT.md`, `php forge credentials`, `php forge update --local`, `php forge start`, or npm setup. Covers pages, models, resources, repeaters, editable content, translations, routes, roles, permissions, external modules, component overrides, and UI/styling that must reuse `wonder-image/lib`. Do not use for the `wonder-image/app` core, direct edits under `vendor/wonder-image/app`, or the `wonder-image/lib` source.4---56# Wonder Site (new-site based)78## Overview910Use this skill inside wonder-image/new-site or any project scaffolded from it. The repo is the runtime owner. The framework lives in `vendor/wonder-image/app` (Composer, see wi-app for changes there) and the JS/CSS design system lives under `assets/lib/wonder-image/dist/` (copied from npm `wonder-image/lib`). Treat both as upstream — never edit them in place.1112## Glossary1314Shared vocabulary across `wi-app` and `wi-site` (identical wording in both skills):1516- **framework** — `wonder-image/app` (Composer package, github.com/wonder-image/app). Lives at the repo root when wi-app is active; lives at `vendor/wonder-image/app/` inside a site.17- **lib** — `wonder-image/lib` (npm package, github.com/wonder-image/lib). The JS / CSS design system. Source at `node_modules/wonder-image/src/`; compiled copy at `assets/lib/wonder-image/dist/`.18- **scaffold** — `wonder-image/new-site` (github.com/wonder-image/new-site). The site template. The scaffold itself is also a valid site.19- **site** — any project whose `composer.json` depends on `wonder-image/app` (i.e. installs the framework under `vendor/wonder-image/app`). Typically the scaffold or a project derived from it. **Canonical term — prefer "site" over older mixed uses like "consumer project" / "consumer app".**20- **module** — external Composer package `wonder-image/<slug>` discovered via Composer (or filesystem fallback). Ships its own models / resources / routes via `module.json` + a `ModuleInterface` entrypoint.21- **`custom/`** — site-only directory for project pages, components, layouts, routes, config, and helpers. Never present inside the framework.22- **`app/Models` / `app/Resources`** — site PSR-4 roots (`App\Models\...` / `App\Resources\...`). Distinct from the framework's `class/App/Models` / `class/App/Resources` (`Wonder\App\Models\...` / `Wonder\App\Resources\...`).2324## When to switch to wi-app2526Stop and switch to [`wi-app`](../wi-app/SKILL.md) when **any** of these signals are true — the work belongs in the framework, not in this site (the frontmatter SKIP block already encodes the router-side check; this is the working-time version):2728- the repo's `composer.json` declares `"name": "wonder-image/app"` (you are inside the framework repo, not a site).29- the requested change lives under `vendor/wonder-image/app/`. Never patch vendor from a site. Either reshape the change to live in `custom/` / `app/Models` / `app/Resources` (stays wi-site), or open the change against the framework repo (then wi-app applies).30- you need to add or modify a `Model` / `Resource` base class, a `FormField` helper, an element under `class/Elements/`, a theme renderer under `class/Themes/{Wonder,Bootstrap}/`, a route in `app/config/routes/*`, the module discovery flow, the bootstrap order, the permission builder registry at `app/config/app/permission.php`, or a shared user-management resource.31- the task is "add a new form input type", "change how the framework renders inputs in Wonder vs Bootstrap", "extend the permission builder", "register a new console command source", or any work that **defines** (rather than uses) framework behavior.32- working in `wonder-image/lib` (the JS / CSS design-system source) — that is a different repo entirely; neither wi-site nor wi-app applies.3334## Non-Negotiable Rules3536- Never edit `vendor/`, `node_modules/`, or `assets/lib/wonder-image/dist/`. The last one is regenerated by `npm install` from `wonder-image/lib`.37- Never patch `vendor/wonder-image/app` from a site task. If the change belongs there, switch to wi-app.38- Never run these Forge commands from this skill:39 - `php forge config`40 - `php forge credentials`41 - `php forge provision`42 - `php forge db:init`43 - `php forge build`44- Every user-facing string goes through `__t(...)` with entries in `lang/{locale}/*.json` (any number of JSON files: `pages.json`, `components.json`, `emails.json`, `legal.json`, plus any new ones the site needs). URLs go through **`__r(string $name, array $parameters = [])`** (preferred — builds the URL from a named route, picks up the active locale, survives route renames). Use `__u(string $path)` only when there is no named route and you must build a URL from a free path (e.g. `__u('contact')`). No hardcoded copy or language prefixes in PHP.45- Before writing new CSS classes, JS behavior, or UI structure, inspect `wonder-image/lib` and reuse the existing design system. Full UI rulebook in `references/style-and-lib.md` — read it for any UI / styling / design-system task. The default mode is **USE the lib, do not MODIFY it**.46- Never hardcode colors (HEX / RGB / HSL), introduce `.wi-*` (or any other) prefix-based naming, or build a parallel CSS system. Detect `{ASSETS_VERSION}` dynamically — do not assume `0.0/` or any other version.47- Prefer external Composer modules `wonder-image/<slug>` over project-embedded module code.48- Place PSR-4 classes under `app/Models` and `app/Resources` with namespace `App\Models` / `App\Resources`. Place project pages, components, layout overrides, routes, config, and helpers under `custom/`.49- The canonical model / table flow is `Model::tableSchema()` + `Model::dataSchema()`. Do not invent parallel table definition systems alongside it.5051## Start Sequence52530. **Read `PRODUCT.md` at the site root first.** It defines register (brand vs product), `site_type`, target users, brand personality, voice/tone, design principles. Everything you do next must be coherent with what it says — placement choices, copy, suggestions of modules, UI direction.5455 **If `PRODUCT.md` is missing or its required sections are empty, do NOT proceed with the user's task yet.** Run the interview procedure in [`references/product-md.md` § Compilation procedure](references/product-md.md#compilation-procedure-interview-driven): ask 2–4 focused questions at a time with `AskUserQuestion`, save answers into `PRODUCT.md` as they come, and continue interviewing until you have **at least 80% project clarity** — operationalized as: all 6 required sections filled (`Register`, `Site type`, `Target users`, `Brand personality`, `Voice / tone`, `Design principles`) plus at least one of (`Anti-references`, `Asset paths`). Only then proceed with the original task. Reason: the alternative is generic output that the user will have to fix later — the 10–15 minutes spent interviewing pay back on every subsequent decision in the session and in future sessions.5657 The interview is sequential and adaptive: if the user already mentioned something in passing (e.g. "abbiamo un brand di moda"), pre-fill the relevant section and ask for confirmation rather than re-asking from scratch. Full schema in [`references/product-md.md`](references/product-md.md); copy-paste template in [`references/examples.md` §6](references/examples.md#6-productmd--brand-and-project-context).581. Classify the task:59 - page or component work60 - UI / styling / design-system work61 - model, resource, repeater, or table work62 - backend-editable content63 - permissions, roles, or user areas64 - translation, locale URLs, or content text65 - module integration66 - setup, runtime, or local environment672. Read only the reference that matches the task (see Task Routing below). For copy-paste scaffolds (Model + Resource skeleton, frontend page, `pages.json` entry, `permissions.php` extension, `modules.php`), jump straight to [`references/examples.md`](references/examples.md).683. Decide whether the work belongs in `custom/`, `app/`, an external `wonder-image/<slug>` module, or actually in the framework (switch to wi-app).694. Refuse the wrong placement: no direct `vendor/` patching, no hand-edited `node_modules/` or `assets/lib/wonder-image/dist/`, no parallel user-management pages, no custom CSS inside `assets/{ASSETS_VERSION}/css/set-up/`.7071## Task Routing7273### Brand, copywriting, voice, site type74Read [`references/product-md.md`](references/product-md.md). `PRODUCT.md` at site root is the source of truth for register, target users, brand personality, voice/tone, design principles, and `site_type` (`landing` / `corporate` / `blog` / `ecom` / `rsvp`). Copy lives in `lang/{locale}/*.json` and must respect the voice declared in `PRODUCT.md`. For deep UI critique / polish / audit beyond Wonder's reuse-first placement rules, hand off to the companion skill [`impeccable`](https://github.com/pbakaus/impeccable) (`npx skills add pbakaus/impeccable` — it reads the same `PRODUCT.md` natively). Do **not** create a `DESIGN.md` — Wonder's `color.css` + `root.css` + [`style-and-lib.md`](references/style-and-lib.md) are authoritative for visual tokens.7576### Page or component77Read `references/implementation-playbook.md` and `references/style-and-lib.md`. Copy-paste skeleton for a frontend page in [`references/examples.md`](references/examples.md#2-frontend-page-customviewpagesfrontendaboutphp).78- For a reusable header driven by one recursive navigation tree, read [`references/header-navigation.md`](references/header-navigation.md). It defines the `classic` / `mega` contract, `list` default, optional `card` presentation, action links, appearance options, desktop hover behavior, and the mobile cascade.79- Pages go under `custom/view/pages/{frontend,backend}/...`.80- Component overrides mirror the framework path under `custom/view/components/{frontend,backend}/...`.81- Reuse `\Wonder\View\View::component(...)` over manual `include`.82- Inspect existing page components before adding new markup.8384### UI / styling / design system85Read `references/style-and-lib.md` **first**. Applies to every task touching buttons, inputs, forms, modals, cards, alerts, badges, typography, images, interactive elements, color tokens, root variables, or custom CSS / JS.86- Default mode: **USE** the lib, do not **MODIFY** it. Modifying `wonder-image/lib` requires an explicit user request.87- Reuse existing lib classes and tokens before writing anything new. No `.wi-*` (or other) prefix-based naming. No parallel CSS system. No hardcoded colors.88- Token files: `assets/{ASSETS_VERSION}/css/set-up/color.css` and `root.css`. Custom CSS / JS goes under `assets/{ASSETS_VERSION}/css/` and `assets/{ASSETS_VERSION}/js/` — never inside `set-up/`.89- Detect `{ASSETS_VERSION}` from the actual `assets/` directory before reading or writing token files.90- End every UI task with the **Required Final Report** and **Pre-Submit Checklist** in `references/style-and-lib.md`.9192### Model, resource, repeater, or table — site postilla93Read `references/implementation-playbook.md` for the placement workflow, then start from the skeleton in [`references/examples.md`](references/examples.md#1-skeleton-model--resource). For the full API contract (method signatures, lifecycle, registry behavior, repeater details), read `wi-app/references/model-and-resource.md` — install wi-app alongside wi-site to have it available locally.9495Steps for a new site Model + Resource:96971. Create the Model under `app/Models/<Name>.php`, namespace `App\Models`, extending the framework Model base.982. Define SQL in `Model::tableSchema()`. Define data behavior in `Model::dataSchema()`.993. Create the Resource under `app/Resources/<Name>Resource.php`, namespace `App\Resources`, bound to the Model.1004. Define `formSchema()` for backend inputs, `permissionSchema()` for route gating, `navigationSchema()` for nav placement.1015. Use `FormField::repeater(...)` + `RepeaterColumn` for repeatable rows; `CustomPageSchema` only for non-CRUD pages.1026. Run `composer dump-autoload`, then `php forge update --local` to apply runtime generation.103104The canonical flow is `Model::tableSchema()` + `Model::dataSchema()`. Do not invent parallel table-definition files alongside it.105106### Backend-editable content107Read `references/implementation-playbook.md`. Prefer a real `Model` + `Resource` flow. Connect media to existing media resources. Never store editable content in static arrays or loose files.108109### Permissions, roles, or user areas — site postilla110The full builder API, framework user resources, and runtime `$PERMITS` export live in **wi-app** at `wi-app/references/permissions-and-users.md`. In a site, the only place to touch is:111112- `custom/config/permissions.php` — extends or overrides the registry after the base file (`app/config/app/permission.php` in the framework) and the module merge have run. Copy-paste skeleton in [`references/examples.md`](references/examples.md#4-customconfigpermissionsphp--extend-the-builder-registry).113114Steps to add or override a site permission:1151161. Open `custom/config/permissions.php`.1172. Extend the builder registry already initialized in `app/config/app/permission.php` and then merged with module permissions.1183. Reference the resulting permission key from any project `Resource::permissionSchema()` and from navigation authority gates.1194. Do not build parallel user-management pages — user CRUD is centralized in the shared framework resources. If a site truly needs a different user flow, that is a framework-level change → switch to wi-app.120121If wi-app is not yet installed locally, run `npx skills add wonder-image/skills --skill wi-app` to make the full reference available.122123### Translation, locale URLs, content text124Read `references/workflows.md`. Sample `lang/it/pages.json` entry in [`references/examples.md`](references/examples.md#3-langitpagesjson).125- Strings live in `lang/{locale}/*.json` — any number of JSON files. The site ships `pages.json`, `components.json`, `emails.json`, `legal.json` by default; new ones (e.g. `lang/{locale}/terms.json`) are picked up automatically.126- Access translated strings via `__t("path.to.key")`.127- Build URLs:128 - **Prefer `__r(string $name, array $parameters = [])`** — URL from a named route. Works for every route registered in `app/config/routes/` or `custom/routes/`, including frontend pages, resource CRUD routes, and custom backend routes. Survives slug / path changes because it resolves by name.129 - Fallback to `__u(string $path)` only when no named route exists and you must build a locale-aware URL from a free path string (e.g. `<a href="<?= __u('contact') ?>">`).130131### Module integration132Read `references/project-structure.md` and `references/workflows.md`.133- Prefer external Composer packages `wonder-image/<slug>` over embedded code.134- Enable modules in `custom/config/modules.php` — copy-paste skeleton in [`references/examples.md`](references/examples.md#5-customconfigmodulesphp--enable-an-external-composer-module).135136### Setup, runtime, or local environment137Read `references/workflows.md`. From the project root:138- `composer install` (also runs `php forge config` via Composer scripts)139- `npm install` (copies `wonder-image/lib` into `assets/lib/wonder-image/dist/`)140- `php forge credentials` (only when the user explicitly requests Bitwarden `dev-shared` recovery; writes secrets into `.env`)141- `php forge update --local` (applies DB and runtime generation)142- `php forge start` (runs the local server, may fill missing `.env`)143144## Validation145146- Run `php -l` on every touched PHP file.147- Run `composer dump-autoload` when PSR-4 classes are added, moved, or renamed.148- For integration-sensitive changes: `php forge update --local` then `php forge start`.149- Re-run `npm install` only when changes depend on `assets/lib/wonder-image/dist/` from `wonder-image/lib`.150151## Output Expectations152153- Name the concrete site paths changed (e.g. `custom/view/pages/frontend/about.php`, `app/Models/Project.php`, `lang/it/pages.json`).154- State explicitly when a requested change actually belongs in the framework (→ wi-app) or in `wonder-image/lib`.155- List translation file updates, permission/authority changes, and Forge/npm rebuild steps when relevant.156- Refuse, with a one-line reason, any edit to `vendor/`, `node_modules/`, `assets/lib/wonder-image/dist/`, or any Forge-generated file.