# Wi Site

> 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.

- Skill: `wonder-image/wi-site` (Agent Skill, multi-file: 8 files)
- Install (CLI): `npx skillmds@latest add wonder-image/wi-site`
- Raw SKILL.md: https://api.skillmd.com/api/skills/wonder-image/wi-site/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: wonder-image (https://skillmd.com/u/wonder-image)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/wonder-image/wi-site

---


# 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`](../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):

- 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

0. **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](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.

   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).
1. 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
2. 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).
3. Decide whether the work belongs in `custom/`, `app/`, an external `wonder-image/<slug>` module, or actually in the framework (switch to wi-app).
4. 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`](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.

### 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`](references/examples.md#2-frontend-page-customviewpagesfrontendaboutphp).
- 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.
- 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`](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.

Steps for a new site Model + Resource:

1. Create the Model under `app/Models/<Name>.php`, namespace `App\Models`, extending the framework Model base.
2. Define SQL in `Model::tableSchema()`. Define data behavior in `Model::dataSchema()`.
3. Create the Resource under `app/Resources/<Name>Resource.php`, namespace `App\Resources`, bound to the Model.
4. Define `formSchema()` for backend inputs, `permissionSchema()` for route gating, `navigationSchema()` for nav placement.
5. Use `FormField::repeater(...)` + `RepeaterColumn` for repeatable rows; `CustomPageSchema` only for non-CRUD pages.
6. 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`](references/examples.md#4-customconfigpermissionsphp--extend-the-builder-registry).

Steps to add or override a site permission:

1. Open `custom/config/permissions.php`.
2. Extend the builder registry already initialized in `app/config/app/permission.php` and then merged with module permissions.
3. Reference the resulting permission key from any project `Resource::permissionSchema()` and from navigation authority gates.
4. 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`](references/examples.md#3-langitpagesjson).
- 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`](references/examples.md#5-customconfigmodulesphp--enable-an-external-composer-module).

### 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.

