diff --git a/.agents/skills/jahia-content-create-content/SKILL.md b/.agents/skills/jahia-content-create-content/SKILL.md index b53b90ed..d9cab872 100644 --- a/.agents/skills/jahia-content-create-content/SKILL.md +++ b/.agents/skills/jahia-content-create-content/SKILL.md @@ -16,6 +16,7 @@ Creates content nodes in a running Jahia instance using the GraphQL JCR mutation - GraphQL endpoint: `http://localhost:8080/modules/graphql` **Auth pattern — always use both flags:** + ```bash curl -u root:root1234 \ -H "Content-Type: application/json" \ @@ -64,6 +65,7 @@ wait # all uploads complete in parallel > ⚠️ Always include `mixins: ["jmix:image"]` in the upload. Without it, the file node **cannot be used as a WEAKREFERENCE** in image properties. To collect UUIDs after parallel uploads, query them in one batch: + ```bash curl -s -u root:root1234 -H "Content-Type: application/json" -H "Origin: http://localhost:8080" \ -X POST http://localhost:8080/modules/graphql \ @@ -113,8 +115,18 @@ curl -s -u root:root1234 \ ``` The response contains the UUID: + ```json -{"data":{"jcr":{"addNode":{"addChild":{"content":{"setValue":true},"contentType":{"setValue":true}},"uuid":"xxxxxxxx-..."}}}} +{ + "data": { + "jcr": { + "addNode": { + "addChild": { "content": { "setValue": true }, "contentType": { "setValue": true } }, + "uuid": "xxxxxxxx-..." + } + } + } +} ``` ### Use a file UUID as an image property @@ -128,6 +140,7 @@ properties: [ ``` > After uploading, publish the files folder so images are accessible on the live site: +> > ```bash > curl -s -u root:root1234 -H "Content-Type: application/json" -H "Origin: http://localhost:8080" \ > -X POST http://localhost:8080/modules/graphql \ @@ -202,6 +215,7 @@ curl -s -u root:root1234 -H "Content-Type: application/json" -H "Origin: http:// ## Step 1 — Identify target site and content folder Standard content folder paths: + - `/sites//contents/articles/` — for article nodes - `/sites//contents/tutorials/` — for tutorial nodes - `/sites//contents/` — for any other content folder @@ -238,15 +252,16 @@ curl -s -u root:root1234 \ ### Property rules -| Situation | GraphQL syntax | -|-----------|---------------| -| i18n property (declared `i18n` in CND) | `{name: "body", value: "...", language: "en"}` | -| Non-i18n property | `{name: "product", value: "jahia"}` | -| Title (from `mix:title`) | `{name: "jcr:title", value: "...", language: "en"}` | -| Date property | `{name: "updatedAt", value: "2024-01-15T00:00:00.000Z", type: DATE}` | -| Multiple values | `{name: "tags", values: ["a", "b"]}` | +| Situation | GraphQL syntax | +| -------------------------------------- | -------------------------------------------------------------------- | +| i18n property (declared `i18n` in CND) | `{name: "body", value: "...", language: "en"}` | +| Non-i18n property | `{name: "product", value: "jahia"}` | +| Title (from `mix:title`) | `{name: "jcr:title", value: "...", language: "en"}` | +| Date property | `{name: "updatedAt", value: "2024-01-15T00:00:00.000Z", type: DATE}` | +| Multiple values | `{name: "tags", values: ["a", "b"]}` | ### Node name rules + - Use lowercase kebab-case: `my-article`, `getting-started` - No spaces, no special characters - Must be unique within the parent folder @@ -314,14 +329,14 @@ curl -s -u root:root1234 \ ## Common errors -| Error | Cause | Fix | -|-------|-------|-----| -| `Permission denied` | Missing `Origin` header | Add `-H "Origin: http://localhost:8080"` | -| `Couldn't find definition for property X` | Wrong property name or non-i18n prop given with `language:` | Check CND definition; remove `language:` for non-i18n props | -| `ConstraintViolationException: mandatory property` | A mandatory CND property was not provided | Provide all mandatory properties | -| `ItemExistsException` | Node name already taken | Use `useAvailableNodeName: true` or choose a different name | -| WEAKREFERENCE image constraint error | Uploaded file missing `jmix:image` mixin | Always include `mixins: ["jmix:image"]` in the `addNode` upload mutation | -| `deletePropertiesBatch fails with missing required fields` | `language` is NON_NULL in `InputJCRDeletedProperty` — required even for non-i18n properties | Always provide `language: "en"` in every `deletePropertiesBatch` entry | +| Error | Cause | Fix | +| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ | +| `Permission denied` | Missing `Origin` header | Add `-H "Origin: http://localhost:8080"` | +| `Couldn't find definition for property X` | Wrong property name or non-i18n prop given with `language:` | Check CND definition; remove `language:` for non-i18n props | +| `ConstraintViolationException: mandatory property` | A mandatory CND property was not provided | Provide all mandatory properties | +| `ItemExistsException` | Node name already taken | Use `useAvailableNodeName: true` or choose a different name | +| WEAKREFERENCE image constraint error | Uploaded file missing `jmix:image` mixin | Always include `mixins: ["jmix:image"]` in the `addNode` upload mutation | +| `deletePropertiesBatch fails with missing required fields` | `language` is NON_NULL in `InputJCRDeletedProperty` — required even for non-i18n properties | Always provide `language: "en"` in every `deletePropertiesBatch` entry | --- @@ -339,9 +354,9 @@ mutation { jcr { mutateNode(pathOrId: "/sites/mySite/home/features/my-card") { addMixins(mixins: ["jmix:internalLink"]) - setPropertiesBatch(properties: [ - {name: "j:linkType", value: "internal"} - ]) { path } + setPropertiesBatch(properties: [{ name: "j:linkType", value: "internal" }]) { + path + } } } } @@ -365,11 +380,15 @@ mutation { jcr { mutateNode(pathOrId: "/sites/mySite/home/features/my-card") { addMixins(mixins: ["jmix:externalLink"]) - setPropertiesBatch(properties: [ - {name: "j:linkType", value: "external"} - {name: "j:url", value: "https://example.com", language: "en"} - {name: "j:linkTitle", value: "Visit Example", language: "en"} - ]) { path } + setPropertiesBatch( + properties: [ + { name: "j:linkType", value: "external" } + { name: "j:url", value: "https://example.com", language: "en" } + { name: "j:linkTitle", value: "Visit Example", language: "en" } + ] + ) { + path + } } } } diff --git a/.agents/skills/jahia-content-explore-structure/SKILL.md b/.agents/skills/jahia-content-explore-structure/SKILL.md index fcefbe2e..d23d3e95 100644 --- a/.agents/skills/jahia-content-explore-structure/SKILL.md +++ b/.agents/skills/jahia-content-explore-structure/SKILL.md @@ -25,6 +25,7 @@ Use this skill **before** creating content on an unfamiliar Jahia site. It produ Use GraphQL aliases to retrieve everything you need in a **single HTTP request**: site metadata, page structure, file assets, and available content types. First, find the site key: + ```bash curl -s -u root:root1234 -H "Content-Type: application/json" -H "Origin: http://localhost:8080" \ -X POST http://localhost:8080/modules/graphql \ @@ -32,6 +33,7 @@ curl -s -u root:root1234 -H "Content-Type: application/json" -H "Origin: http:// ``` Then run the full batch query (replace `SITE_KEY` and `TEMPLATE_MODULE`): + ```bash curl -s -u root:root1234 \ -H "Content-Type: application/json" -H "Origin: http://localhost:8080" \ @@ -40,6 +42,7 @@ curl -s -u root:root1234 \ ``` From the response: + - `site.properties` → `j:templatesSet` (the template module name) and `j:defaultLanguage` - `home.children` → page area structure; look for area nodes and check their children to see which content types are in use - `files.children` → existing file folders and UUIDs diff --git a/.agents/skills/jahia-content-move-content/SKILL.md b/.agents/skills/jahia-content-move-content/SKILL.md index f86a0752..9f22e45c 100644 --- a/.agents/skills/jahia-content-move-content/SKILL.md +++ b/.agents/skills/jahia-content-move-content/SKILL.md @@ -16,6 +16,7 @@ Reorganizes the JCR content tree — moving nodes into sub-folders, renaming the - GraphQL endpoint: `http://localhost:8080/modules/graphql` **Always include both auth flags:** + ```bash curl -s -u root:root1234 \ -H "Content-Type: application/json" \ @@ -214,13 +215,13 @@ curl -s -u root:root1234 \ ## Common errors -| Error | Cause | Fix | -|-------|-------|-----| -| `Permission denied` | Missing `Origin` header | Add `-H "Origin: http://localhost:8080"` | -| `ItemExistsException` | A node with that name already exists at the destination | Choose a different name or use `rename` after moving | -| `PathNotFoundException` | Source or destination path doesn't exist | Verify paths with `nodeByPath` first | -| `move` returns `null` | Node was already at that location | Verify the current path first | -| Content disappears from live after move | Move unpublishes — normal JCR behaviour | Run `publish` after every move | +| Error | Cause | Fix | +| --------------------------------------- | ------------------------------------------------------- | ---------------------------------------------------- | +| `Permission denied` | Missing `Origin` header | Add `-H "Origin: http://localhost:8080"` | +| `ItemExistsException` | A node with that name already exists at the destination | Choose a different name or use `rename` after moving | +| `PathNotFoundException` | Source or destination path doesn't exist | Verify paths with `nodeByPath` first | +| `move` returns `null` | Node was already at that location | Verify the current path first | +| Content disappears from live after move | Move unpublishes — normal JCR behaviour | Run `publish` after every move | --- diff --git a/.agents/skills/jahia-content-query-content/SKILL.md b/.agents/skills/jahia-content-query-content/SKILL.md index ebeea30a..2893f7d7 100644 --- a/.agents/skills/jahia-content-query-content/SKILL.md +++ b/.agents/skills/jahia-content-query-content/SKILL.md @@ -16,6 +16,7 @@ Retrieves JCR content from a running Jahia instance using the GraphQL JCR query - GraphQL endpoint: `http://localhost:8080/modules/graphql` **Auth pattern — always use both flags:** + ```bash curl -u root:root1234 \ -H "Content-Type: application/json" \ @@ -130,11 +131,11 @@ SELECT * FROM [ns:typeName] WHERE ISDESCENDANTNODE('/sites/mySite') ORDER BY [jc ## Common errors -| Error | Cause | Fix | -|-------|-------|-----| -| `Permission denied` | Missing `Origin` header | Add `-H "Origin: http://localhost:8080"` | -| i18n properties returned empty | `language:` not specified | Add `language: "en"` to `properties()` call | -| Node not found | Wrong path or node doesn't exist | Verify path with `nodeByPath(path: "/sites")` first | +| Error | Cause | Fix | +| ------------------------------ | -------------------------------- | --------------------------------------------------- | +| `Permission denied` | Missing `Origin` header | Add `-H "Origin: http://localhost:8080"` | +| i18n properties returned empty | `language:` not specified | Add `language: "en"` to `properties()` call | +| Node not found | Wrong path or node doesn't exist | Verify path with `nodeByPath(path: "/sites")` first | --- diff --git a/.agents/skills/jahia-content-translate-content/SKILL.md b/.agents/skills/jahia-content-translate-content/SKILL.md index 7c0c87ad..97f04dde 100644 --- a/.agents/skills/jahia-content-translate-content/SKILL.md +++ b/.agents/skills/jahia-content-translate-content/SKILL.md @@ -16,6 +16,7 @@ Adds languages to a Jahia site and populates i18n properties on existing content - GraphQL endpoint: `http://localhost:8080/modules/graphql` **Always include both auth flags:** + ```bash curl -s -u root:root1234 \ -H "Content-Type: application/json" \ @@ -274,13 +275,13 @@ curl -s -u root:root1234 \ ## Common errors -| Error | Cause | Fix | -|-------|-------|-----| -| `Permission denied` | Missing `Origin` header | Add `-H "Origin: http://localhost:8080"` | -| i18n property returned empty after set | Missing `language:` in `properties()` query | Add `language: "fr"` to read call | -| `ConstraintViolationException` on title set | Mandatory i18n field not set first | Use `setPropertiesBatch` with all mandatory fields in one call | -| Language not appearing in site | `j:languages` mutation only had the new language | Pass the full list: `["en", "fr"]` | -| Choicelist key changed per language | Property incorrectly declared `i18n` in CND | Remove `i18n` from the CND property; translate keys in the view | +| Error | Cause | Fix | +| ------------------------------------------- | ------------------------------------------------ | --------------------------------------------------------------- | +| `Permission denied` | Missing `Origin` header | Add `-H "Origin: http://localhost:8080"` | +| i18n property returned empty after set | Missing `language:` in `properties()` query | Add `language: "fr"` to read call | +| `ConstraintViolationException` on title set | Mandatory i18n field not set first | Use `setPropertiesBatch` with all mandatory fields in one call | +| Language not appearing in site | `j:languages` mutation only had the new language | Pass the full list: `["en", "fr"]` | +| Choicelist key changed per language | Property incorrectly declared `i18n` in CND | Remove `i18n` from the CND property; translate keys in the view | --- diff --git a/.agents/skills/jahia-content/SKILL.md b/.agents/skills/jahia-content/SKILL.md index f293ec7f..cbe52994 100644 --- a/.agents/skills/jahia-content/SKILL.md +++ b/.agents/skills/jahia-content/SKILL.md @@ -25,6 +25,7 @@ curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/cms/login Run both checks in parallel to understand what's currently in the CMS: ### A. List available sites + ```bash curl -s -u root:root1234 \ -H "Content-Type: application/json" \ @@ -34,6 +35,7 @@ curl -s -u root:root1234 \ ``` ### B. List top-level content folders + ```bash curl -s -u root:root1234 \ -H "Content-Type: application/json" \ @@ -60,16 +62,16 @@ curl -s -u root:root1234 \ Use the task description to pick the right skill(s): -| What the user wants to do | Skill | -|---------------------------|-------| -| Explore an unknown site's content types, property names, enum values, mixins | **`/jahia-content-explore-structure`** | -| Find out what content exists, audit the tree, run a search | **`/jahia-content-query-content`** | -| Create pages, articles, tutorials, folders, populate a site | **`/jahia-content-create-content`** | -| Move, rename, restructure content into sub-folders | **`/jahia-content-move-content`** | -| Translate existing content to another language | **`/jahia-content-translate-content`** | -| Publish content to the live site | Use `publish` mutation (see below) | -| Delete content | Use `deleteNode` mutation (see below) | -| Do several of the above in sequence | Run the skills in order — start with **explore-structure** if site is unfamiliar, then create or move | +| What the user wants to do | Skill | +| ---------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | +| Explore an unknown site's content types, property names, enum values, mixins | **`/jahia-content-explore-structure`** | +| Find out what content exists, audit the tree, run a search | **`/jahia-content-query-content`** | +| Create pages, articles, tutorials, folders, populate a site | **`/jahia-content-create-content`** | +| Move, rename, restructure content into sub-folders | **`/jahia-content-move-content`** | +| Translate existing content to another language | **`/jahia-content-translate-content`** | +| Publish content to the live site | Use `publish` mutation (see below) | +| Delete content | Use `deleteNode` mutation (see below) | +| Do several of the above in sequence | Run the skills in order — start with **explore-structure** if site is unfamiliar, then create or move | --- @@ -78,6 +80,7 @@ Use the task description to pick the right skill(s): Use these when the task is simple enough to not need a full sub-skill. ### Publish a node (and all its children) + ```bash curl -s -u root:root1234 \ -H "Content-Type: application/json" \ @@ -87,6 +90,7 @@ curl -s -u root:root1234 \ ``` ### Publish all content at once + ```bash curl -s -u root:root1234 \ -H "Content-Type: application/json" \ @@ -96,6 +100,7 @@ curl -s -u root:root1234 \ ``` ### Delete a node + ```bash curl -s -u root:root1234 \ -H "Content-Type: application/json" \ @@ -105,6 +110,7 @@ curl -s -u root:root1234 \ ``` ### Update a property on an existing node + ```bash curl -s -u root:root1234 \ -H "Content-Type: application/json" \ diff --git a/.agents/skills/jahia-dev-accessibility/SKILL.md b/.agents/skills/jahia-dev-accessibility/SKILL.md index 786609ba..e5ffd3e1 100644 --- a/.agents/skills/jahia-dev-accessibility/SKILL.md +++ b/.agents/skills/jahia-dev-accessibility/SKILL.md @@ -97,15 +97,18 @@ Common violations in Jahia JS modules and their fixes: ### 🔴 Critical / Serious **`color-contrast`** — text fails WCAG AA contrast ratio (4.5:1 for normal text, 3:1 for large text) + ```css /* Bad */ -color: #aaa; background: #fff; +color: #aaa; +background: #fff; /* Fix — use a contrast checker: https://webaim.org/resources/contrastchecker/ */ color: #595959; /* 7:1 ratio on white */ ``` **`image-alt`** — `` missing `alt` attribute + ```tsx /* Bad */ @@ -113,9 +116,11 @@ color: #595959; /* 7:1 ratio on white */ /* Fix — use content from CND, fall back to empty string for decorative */ {props.imageAlt ``` + Add `- imageAlt (string) i18n` to the CND and `imageAlt?: string` to `types.ts`. **`button-name`** — ` @@ -125,20 +130,21 @@ Add `- imageAlt (string) i18n` to the CND and `imageAlt?: string` to `types.ts`. ``` **`landmark-one-main`** — page has no `
` landmark + ```tsx /* Fix — wrap page content in
*/ -
- {/* page content */} -
+
{/* page content */}
``` **`page-has-heading-one`** — page has no `

` element + ```tsx /* Fix — ensure the hero or first section renders an

*/

{props.title}

``` **`link-name`** — `
` with no accessible text + ```tsx /* Bad */ @@ -150,6 +156,7 @@ Add `- imageAlt (string) i18n` to the CND and `imageAlt?: string` to `types.ts`. ### 🟡 Moderate **`heading-order`** — headings skip levels (e.g. `

` → `

`) + ```tsx /* Review: the first heading in a component should be h2 (after the page h1) */ /* Section titles: h2, subsections: h3 */ @@ -159,6 +166,7 @@ Add `- imageAlt (string) i18n` to the CND and `imageAlt?: string` to `types.ts`. Wrap page sections in semantic elements: `
`, `