Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
405 changes: 77 additions & 328 deletions en/frontend/micro-frontends/build-system.md

Large diffs are not rendered by default.

2,243 changes: 173 additions & 2,070 deletions en/frontend/micro-frontends/compliance-checklist.md

Large diffs are not rendered by default.

38 changes: 38 additions & 0 deletions en/frontend/micro-frontends/configuration-casing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
title: "Configuration and Casing"
description: "Casing rules at backend facade, registry, and frontend configuration boundaries."
---

# Configuration and Casing

Casing follows the schema boundary. Never recursively convert a configuration object.

| Boundary | Rule | Examples |
|---|---|---|
| Backend facade requirement names | top-level `lower_case_with_underscore` | `custom_css`, `css_variables` |
| Registry fields | each field follows its documented registry schema | `base_path`, `entry_point`, `tag_name` |
| Nested frontend configuration carried by backend YAML | preserve lower camelCase | `customCSS`, `themeConfig`, `iconifyIcons` |
| Frontend AppConfig and package metadata | lower camelCase | `configOverrides`, `hostCssKeys` |

```yaml
config_overrides:
customization:
customCSS: ""
cssVariables: {}
routePrefix: /admin

proxy:
injections:
css:
themeConfig: true
customCss: true
iframe: true
```

Only the backend wrapper keys are snake case in this example. Nested frontend objects are passed through and retain their defined casing.

## Temporary mountRoute exception

`meta.mountRoute` is a current backend compatibility bug. The intended backend field is `meta.mount_route`, but existing deployments require `mountRoute` until the backend correction ships. Treat it as one explicit exception, not evidence that registry or backend fields are generally camelCase.

Compliance must version this exception so it can be removed when the backend schema changes.
133 changes: 133 additions & 0 deletions en/frontend/micro-frontends/custom-composites.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
---
title: "Custom Composites"
description: "Contract-first exceptions for controls whose required affordance cannot be provided by PrimeVue."
---

# Custom Composites

Custom controls are exceptions, not an alternative component library.

## Admission test

A custom control is accepted only when:

1. PrimeVue cannot provide or compose the intended semantics, interaction, and affordance.
2. The exception records rejected PrimeVue compositions.
3. It names an exact generated PrimeVue sibling contract and contract hash.
4. Every property that sibling contract classifies `shared-runtime` has an exact source mapping.
5. A fixed utility is accepted only when the sibling contract classifies that exact property `platform-invariant`.
6. Novel geometry and behavior are isolated and documented.
7. Accessibility and visual evidence pass.

Data-shape equivalence is not affordance equivalence. A multi-option `SelectButton` may represent three values but does not look or behave like a sliding three-position toggle. Conversely, do not invent a `positions` prop for `ToggleSwitch`. Build a reviewed custom sibling only when the affordance requirement is real.

## Module contract

Store a reviewed exception in module-root `wippy-fe.contract.json`:

```json
{
"schemaVersion": "generated-by-selected-contract-tool",
"exceptions": [
{
"id": "module.control.example",
"source": "src/components/ExampleControl.vue",
"sourceSha256": "generated-from-source",
"semanticRole": "documented-role",
"requiredAffordance": "documented-affordance",
"rejectedPrimeVueCompositions": [
{
"components": ["SelectButton"],
"reason": "The reviewed sliding affordance cannot be preserved."
}
],
"visualSibling": {
"component": "ToggleSwitch",
"contractId": "primevue.toggleswitch.portable-appearance",
"contractHash": "generated-from-selected-theme-contract"
},
"sharedAppearanceMappings": [
{
"contractProperty": "root.width",
"part": "root",
"selector": ".example-control",
"source": {
"kind": "css-variable",
"name": "--p-toggleswitch-width"
}
}
],
"platformInvariantUtilities": [],
"moduleLocalProperties": [],
"accessibilityEvidence": {
"manifest": ".local/evidence/accessibility-manifest.json",
"scenarioId": "module.control.example.keyboard",
"resultId": "module.control.example.keyboard.passed",
"build": {
"head": "generated-candidate-commit",
"trackedFrontendDiffSha256": "generated-diff-hash"
}
},
"visualEvidence": {
"manifest": ".local/evidence/visual-manifest.json",
"scenarioId": "module.control.example.light.default",
"captureId": "module.control.example.light.default.component",
"build": {
"head": "generated-candidate-commit",
"trackedFrontendDiffSha256": "generated-diff-hash"
}
}
}
]
}
```

The values shown are schema placeholders, not valid evidence. The complete
mapping is generated from the selected sibling contract; the one-row excerpt is
not a valid exception by itself. Tooling generates the source and contract
hashes. A changed source hash or sibling-contract hash invalidates review.

This page defines the normative fields; it is not a JSON Schema and the
documentation checker only proves that this example retains the required
shape. `wippy-fe-compliance` validates a real module contract against the
selected theme manifest, verifies the hashes and complete property set, and
checks that every evidence reference resolves to the named passing result or
capture from the same candidate build. Accessibility evidence binds the
component `sourceSha256`, hashed files, zero unexpected console errors, and a
passed result. Visual evidence binds canonical before/after/diff files, hashes,
recomputed metrics and disposition, and the matching candidate build. A
string, missing file, missing scenario/result/capture, stale build hash,
`pending`, or unreviewed result does not satisfy the evidence requirement.

`platformInvariantUtilities` and `moduleLocalProperties` may be empty. Never
invent `gap-2`, `w-10`, `rounded-md`, or another fixed utility merely to make a
contract field nonempty. In particular, a ToggleSwitch sibling cannot relabel
width, height, radius, focus geometry, or motion as invariant when its selected
sibling contract classifies those properties `shared-runtime`.

The sibling manifest classifies properties as:

- `shared-runtime`: every custom sibling maps and consumes the published token
or runtime-backed semantic utility.
- `platform-invariant`: a fixed value is permitted only for this exact
property.
- `implementation-private`: internal PrimeVue mechanics do not become
requirements for a custom sibling.

If the required runtime semantic does not exist, fix the shared theme contract first. Never copy the current sibling dimensions or invent a token name.

`sharedAppearanceMappings` is exhaustive, not illustrative: it contains exactly
one mapping for every `shared-runtime` property in the selected sibling
contract, no additional property IDs, the contract part, a stable module
selector, and the exact published source kind and name. Compliance tooling uses
the selector, part, CSS property, and published source to prove the mapping
structurally with PostCSS; a token name in a comment or unrelated selector does
not count. A Tailwind-backed mapping also records unique, exact
`utilityClasses`; after normalization that set must equal the selected sibling
contract source set. `platformInvariantUtilities` contains
`{ "contractProperty": "...", "utility": "..." }` records whose utility equals
the selected sibling contract source. `moduleLocalProperties`, when nonempty,
contains structured property IDs and review reasons rather than a free-form CSS
bag.

No shared `@wippy-fe/ui` package is created for a single exception. Promotion becomes eligible only after a second independent consumer proves the same behavior and portability requirements.
9 changes: 5 additions & 4 deletions en/frontend/micro-frontends/host-less-mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ This isn't an accident or an afterthought. It is what makes:
Every canonical app's `app.html` ships with **one** script tag that decides the boot path at load time:

This is an abbreviated body/boot example. Insert the complete valid import-map
script from [Compliance Checklist §3.3](./compliance-checklist.md#33-apphtml),
updated from the fetched response when the pinned Web Host tag changes.
response described by the [Import-map snapshot algorithm](./build-system.md#import-map-snapshot-algorithm),
updated when the pinned Web Host tag changes.

```html
<!-- URL MUST include a release-tag segment: https://web-host.wippy.ai/<release-tag>/dev-proxy.js -->
Expand Down Expand Up @@ -100,8 +100,9 @@ curl.exe -fsS "https://web-host.wippy.ai/<release-tag>/import-map.json" -o impor
Set the text of the `app.html` `<script type="importmap">` element to the
fetched JSON response verbatim. Do not put comments, ellipsis placeholders, or
hand-written substitutions inside that JSON. The
[compliance checklist §3.3](./compliance-checklist.md#33-apphtml) contains a
valid example for the currently verified release.
The [Build and Dependency Contract](./build-system.md#import-map-snapshot-algorithm)
defines the snapshot and provenance requirements; the fetched release response
provides the exact `imports` object.

Conventions:
- Put **every fetched key** in Rollup externals, including currently unused keys.
Expand Down
Loading